/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ECMASCRIPT_IC_IC_RUNTIME_STUB_H_
#define ECMASCRIPT_IC_IC_RUNTIME_STUB_H_

#include "plugins/ecmascript/runtime/js_function.h"
#include "plugins/ecmascript/runtime/base/config.h"
#include "plugins/ecmascript/runtime/js_tagged_value.h"
#include "plugins/ecmascript/runtime/property_attributes.h"

namespace ark::ecmascript {
class ProfileTypeInfo;

class ICRuntimeStub {
public:
    static inline constexpr uint32_t SlotSizeForGlobalICByName()
    {
        return 1U;
    }

    static inline constexpr uint32_t SlotSizeForICByName()
    {
        return 4U;
    }

    static inline constexpr uint32_t SlotSizeForICByValue()
    {
        // For key we need 3 slots. For one element we need 2 slots.
        // But we store 2 pairs of elements.
        return 4U;
    }

    ARK_INLINE static inline bool HaveICForFunction(JSFunction *func);
    ARK_INLINE static inline JSTaggedValue LoadGlobalICByName(JSThread *thread, JSFunction *func,
                                                              JSTaggedValue globalValue, JSTaggedValue key,
                                                              uint32_t slotId, bool isTryLoad = false);
    ARK_INLINE static inline JSTaggedValue StoreGlobalICByName(JSThread *thread, JSFunction *func,
                                                               JSTaggedValue globalValue, JSTaggedValue key,
                                                               JSTaggedValue value, uint32_t slotId,
                                                               bool isTryStore = false);
    ARK_INLINE static inline JSTaggedValue LoadICByName(JSThread *thread, JSFunction *func, JSTaggedValue receiver,
                                                        JSTaggedValue key, uint32_t slotId);
    ARK_INLINE static inline JSTaggedValue StoreICByName(JSThread *thread, JSFunction *func, JSTaggedValue receiver,
                                                         JSTaggedValue key, JSTaggedValue value, uint32_t slotId);
    ARK_INLINE static inline JSTaggedValue CheckPolyHClass(JSTaggedValue cachedValue, JSHClass *hclass);
    static inline JSTaggedValue LoadICWithHandler(JSThread *thread, JSTaggedValue receiver, JSTaggedValue holder,
                                                  JSTaggedValue handler);
    static inline JSTaggedValue StoreICWithHandler(JSThread *thread, JSTaggedValue receiver, JSTaggedValue holder,
                                                   JSTaggedValue value, JSTaggedValue handler);
    ARK_INLINE static inline void StoreWithTransition(JSThread *thread, JSObject *receiver, JSTaggedValue value,
                                                      JSTaggedValue handler);
    ARK_INLINE static inline JSTaggedValue StorePrototype(JSThread *thread, JSTaggedValue receiver, JSTaggedValue value,
                                                          JSTaggedValue handler);
    ARK_INLINE static inline JSTaggedValue LoadFromField(JSObject *receiver, uint32_t handlerInfo);
    ARK_INLINE static inline void StoreField(JSThread *thread, JSObject *receiver, JSTaggedValue value,
                                             uint32_t handler);
    ARK_INLINE static inline JSTaggedValue LoadGlobal(JSTaggedValue handler);
    ARK_INLINE static inline JSTaggedValue StoreGlobal(JSThread *thread, JSTaggedValue value, JSTaggedValue handler);
    ARK_INLINE static inline JSTaggedValue LoadPrototype(JSThread *thread, JSTaggedValue receiver,
                                                         JSTaggedValue handler);
    ARK_INLINE static inline JSTaggedValue LoadICByValue(JSThread *thread, JSFunction *func, JSTaggedValue receiver,
                                                         JSTaggedValue key, uint32_t slotId);
    ARK_INLINE static inline JSTaggedValue StoreICByValue(JSThread *thread, JSFunction *func, JSTaggedValue receiver,
                                                          JSTaggedValue key, JSTaggedValue value, uint32_t slotId);
    ARK_INLINE static inline JSTaggedValue LoadElement(JSObject *receiver, JSTaggedValue key);
    ARK_INLINE static inline JSTaggedValue StoreElement(JSThread *thread, JSObject *receiver, JSTaggedValue key,
                                                        JSTaggedValue value, ProfileTypeInfo *profileTypeInfo,
                                                        uint32_t slotId);
    ARK_INLINE static inline uint32_t TryToElementsIndex(JSTaggedValue key);

private:
    static inline uint32_t MapSlotId(JSFunction *func, uint32_t slotId);
    static inline ProfileTypeInfo *GetRuntimeProfileTypeInfo(JSFunction *func);
    ARK_NOINLINE static JSTaggedValue LoadMissedICByName(JSThread *thread, ProfileTypeInfo *profileTypeArray,
                                                         JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId);
    ARK_NOINLINE static JSTaggedValue StoreMissedICByName(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                          JSTaggedValue receiver, JSTaggedValue key,
                                                          JSTaggedValue value, uint32_t slotId);
    ARK_NOINLINE static JSTaggedValue LoadMissedICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                          JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId);
    ARK_NOINLINE static JSTaggedValue StoreMissedICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
                                                           JSTaggedValue receiver, JSTaggedValue key,
                                                           JSTaggedValue value, uint32_t slotId);
};
}  // namespace ark::ecmascript

#endif  // ECMASCRIPT_IC_IC_RUNTIME_STUB_H_
